package com.spzx.order.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.spzx.common.core.exception.ServiceException;
import com.spzx.domain.OrderInfo;
import com.spzx.domain.OrderItem;
import com.spzx.domain.OrderLog;
import com.spzx.order.mapper.OrderInfoMapper;
import com.spzx.order.mapper.OrderItemMapper;
import com.spzx.order.mapper.OrderLogMapper;
import com.spzx.order.service.IOrderInfoService;
import com.spzx.product.api.RemoteProductService;
import com.spzx.vo.OrderForm;
import com.spzx.vo.R;
import com.spzx.vo.SkuLockVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 订单Service业务层处理
 */
@Service
public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo> implements IOrderInfoService {
    @Autowired RedisTemplate redisTemplate;

    //生成订单接口
    @Override
    public Long submitOrder(OrderForm orderForm,Long userId) {
        //1 防止订单重复提交
        this.StopReSub1(orderForm,userId);
        //2 判断结算订单项不能为空
        List<OrderItem> orderItemList = orderForm.getOrderItemList();
        if(CollectionUtils.isEmpty(orderItemList)) {
            throw new ServiceException("提交订单商品为空");
        }
        //3 校验价格
        //3.1 orderItemList获取所有skuId集合
        List<Long> skuIdList =
                orderItemList.stream().map(OrderItem::getSkuId).collect(Collectors.toList());
        //查询sku最新价格集合
        R<List<SkuPrice>> skuPriceListR = remoteProductService.getSkuPriceList(skuIdList, SecurityConstants.INNER);
        List<SkuPrice> skuPriceList = skuPriceListR.getData();
        //将skuPriceList转为Map集合（其他属性不要管）
        Map<Long, BigDecimal> map =
                skuPriceList.stream().collect(Collectors.toMap(SkuPrice::getSkuId, SkuPrice::getSalePrice));

        //3.4 比较orderItemList价格和最新价格是否相同，如果不相同，价格变化
        //设立标志位
        String priceCheckResult = "";
        for (OrderItem orderItem : orderItemList) {

            if (orderItem.getSkuPrice().compareTo(map.get(orderItem.getSkuId())) != 0) {
                priceCheckResult += orderItem.getSkuName() + "价格变化了; ";
            }
        }
        if (StringUtils.isEmpty(priceCheckResult)){
            //为空说明价格已经发生变化，远程调用更新购物车价格
            remoteCartService.updateCartPrice(userId,SecurityConstants.INNER);
            throw new ServiceException(priceCheckResult);
        }
        //4 校验库存并锁定库存
        //5 生成订单（订单表添加数据order_info  和  order_item）
        //6 删除购物车选中商品

        //TODO 7 发送延迟消息，实现30分钟没有支付订单，解锁库存

        //TODO 8 下单失败，解锁库存

        //9 返回订单id
        return 1L;
    }

    public void StopReSub1(OrderForm orderForm,Long userId){
        //第二种  在第一种基础之上具备原子性，使用lua脚本
        String userTradeKey = "user:tradeNo:" + userId;
        String scriptText = "if redis.call(\"get\",KEYS[1]) == ARGV[1]\n" +
                "then\n" +
                "    return redis.call(\"del\",KEYS[1])\n" +
                "else\n" +
                "    return 0\n" +
                "end";
        DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
        redisScript.setScriptText(scriptText);
        redisScript.setResultType(Long.class);
        Long flag = (Long) redisTemplate.execute(redisScript,
                Arrays.asList(userTradeKey),
                orderForm.getTradeNo());
        if (flag == 0) {
            throw new ServiceException("请勿重复提交订单，请尝试重试");
        }

    }
    //检查交易号的方法
    public Boolean checkTradeNo(Long userId,String tradeNo){
        String userTradeKey = "user:tradeNo:" + userId;
        String RedisTradeNo = (String) redisTemplate.opsForValue().get(userTradeKey);
        if (RedisTradeNo.equals(tradeNo)){
            return true;
        }
        return false;
    }

}
